"""Trend analysis API endpoints."""

from __future__ import annotations

from typing import Literal

from fastapi import APIRouter, Depends, Query
from sqlalchemy.orm import Session

from app.api.deps import get_current_user, get_db
from app.models.user import User
from app.schemas.trend import (
    MovingAveragePoint,
    RateOfChangePoint,
    TimeSeriesPoint,
    TrendAnalysis,
)
from app.services.trend_service import TrendService

router = APIRouter()


@router.get("/timeseries/{device_id}/{metric_name}", response_model=list[TimeSeriesPoint])
def get_time_series(
    device_id: int,
    metric_name: str,
    interval: Literal["hour", "day"] = Query("hour", description="Aggregation interval"),
    hours: int = Query(24, ge=1, le=720, description="Time window in hours"),
    session: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> list[TimeSeriesPoint]:
    """Get time-series data aggregated by interval.

    Returns data aggregated by hour or day, including:
    - Count of readings in each bucket
    - Min, max, and average values

    Useful for:
    - Visualizing metric trends over time
    - Identifying daily/hourly patterns
    - Reducing data volume for charting

    Examples:
    - Hourly data: GET /trends/timeseries/1/temperature?interval=hour&hours=24
    - Daily data: GET /trends/timeseries/1/pressure?interval=day&hours=168
    """
    service = TrendService(session)
    results = service.get_time_series(device_id=device_id, metric_name=metric_name, interval=interval, hours=hours)

    return [TimeSeriesPoint(**result) for result in results]


@router.get("/moving-average/{device_id}/{metric_name}", response_model=list[MovingAveragePoint])
def get_moving_average(
    device_id: int,
    metric_name: str,
    window_size: int = Query(10, ge=2, le=100, description="Moving average window size"),
    hours: int = Query(24, ge=1, le=720, description="Time window in hours"),
    session: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> list[MovingAveragePoint]:
    """Calculate moving average for metric.

    Returns each data point with its moving average calculated
    over the specified window size.

    Useful for:
    - Smoothing noisy sensor data
    - Identifying underlying trends
    - Filtering out short-term fluctuations

    Example: GET /trends/moving-average/1/temperature?window_size=10&hours=24
    """
    service = TrendService(session)
    results = service.get_moving_average(
        device_id=device_id, metric_name=metric_name, window_size=window_size, hours=hours
    )

    return [MovingAveragePoint(**result) for result in results]


@router.get("/detect/{device_id}/{metric_name}", response_model=TrendAnalysis)
def detect_trend(
    device_id: int,
    metric_name: str,
    hours: int = Query(24, ge=1, le=720, description="Time window in hours"),
    threshold: float = Query(5.0, ge=0.1, le=100.0, description="Trend threshold (percent change)"),
    session: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> TrendAnalysis:
    """Detect trend direction (increasing/decreasing/stable).

    Analyzes the overall trend by comparing first and last values
    in the time window. Classifies as:
    - Increasing: value increased > threshold%
    - Decreasing: value decreased > threshold%
    - Stable: change <= threshold%

    Useful for:
    - Quick trend assessment
    - Alerting on significant changes
    - Monitoring metric stability

    Example: GET /trends/detect/1/temperature?hours=24&threshold=5.0
    """
    service = TrendService(session)
    result = service.detect_trend(
        device_id=device_id, metric_name=metric_name, hours=hours, threshold_percent=threshold
    )

    return TrendAnalysis(**result)


@router.get("/rate-of-change/{device_id}/{metric_name}", response_model=list[RateOfChangePoint])
def get_rate_of_change(
    device_id: int,
    metric_name: str,
    interval_minutes: int = Query(60, ge=1, le=1440, description="Rate calculation interval (minutes)"),
    hours: int = Query(24, ge=1, le=720, description="Time window in hours"),
    session: Session = Depends(get_db),
    current_user: User = Depends(get_current_user),
) -> list[RateOfChangePoint]:
    """Calculate rate of change over time.

    Returns the rate at which the metric is changing, normalized
    to the specified interval (e.g., change per hour).

    Useful for:
    - Detecting rapid changes
    - Monitoring acceleration/deceleration
    - Identifying anomalies in rate patterns

    Example: GET /trends/rate-of-change/1/flow_rate?interval_minutes=60&hours=24
    """
    service = TrendService(session)
    results = service.get_rate_of_change(
        device_id=device_id, metric_name=metric_name, interval_minutes=interval_minutes, hours=hours
    )

    return [RateOfChangePoint(**result) for result in results]
